#include "Player.h"
#include "../Graphic/GraphicManager.h"
#include "../Graphic/TextureManager.h"
#include "../Game/Level.h"
#include "../Game/Game.h"
#include "Bullet.h"
#include <GL/glut.h>
#include <math.h>


//Update player
void cPlayer::Update(float lfTimeStep)
{
  
  //Get game graphic properties
  unsigned int luiGameWidth = cGraphicManager::Get().GetGameWidth();
  unsigned int luiGameHeight = cGraphicManager::Get().GetGameHeight();
  unsigned int luiXScreenOffset = cGraphicManager::Get().GetXScreenOffset();
  unsigned int luiYScreenOffset = cGraphicManager::Get().GetYScreenOffset();
  unsigned int luiTileHeight = cGraphicManager::Get().GetTileHeight();
  unsigned int luiTileWidth = cGraphicManager::Get().GetTileWidth();

  //To control the speed of the player you can only move every 0.075ms
  mfElapsedTime += fabs(lfTimeStep );
  if (mfElapsedTime < 0.225) return;
  
  //Local variables that hold the next position
  unsigned int luiX = muiX;
  unsigned int luiY = muiY;
  //Check walls
  cLevel &lLevel = cLevel::Get();
 
  bool lbMoved = false;
  //Check actions
  if (IsPressed(eIA_MoveUp) )
    {
    luiY--; 
    if ((luiY * luiTileHeight < luiYScreenOffset + (luiTileHeight*4)) && (!lLevel.IsWall( luiX, luiY )))
    {
      if (luiYScreenOffset - luiGameHeight + (luiTileHeight*8) < luiY*luiTileHeight)
        cGraphicManager::Get().SetYScreenOffset( luiYScreenOffset - luiGameHeight + (luiTileHeight*8));
    }
    miLookingAt = eO_North;
    lbMoved = true;
  }

  if (IsPressed(eIA_MoveDown))
  {
    luiY++; 
    if ((luiY * luiTileHeight >= luiYScreenOffset + luiGameHeight - (luiTileHeight*4)) && (!lLevel.IsWall( luiX, luiY )))
    {
      cGraphicManager::Get().SetYScreenOffset( luiYScreenOffset + luiGameHeight - (luiTileHeight*8));
    }
      miLookingAt = eO_South;
      lbMoved = true;
  }

  if (IsPressed(eIA_MoveLeft) )
  {
    luiX--;
    if ((luiX * luiTileWidth < luiXScreenOffset + (luiTileWidth*4)) && (!lLevel.IsWall( luiX, luiY )))
    {
      if ((luiXScreenOffset - luiGameWidth + (luiTileWidth*8))< luiX*luiTileWidth)
      {
        cGraphicManager::Get().SetXScreenOffset( luiXScreenOffset - luiGameWidth + (luiTileWidth*8));
      }
    }
    if (lbMoved)
      miLookingAt += eO_West;
    else
      miLookingAt = eO_West;
  }

  if (IsPressed(eIA_MoveRight))
  {
    luiX++;
    
    if ((luiX * luiTileWidth >= luiXScreenOffset + luiGameWidth - (luiTileWidth*4)) && (!lLevel.IsWall( luiX, luiY )))
    {
      cGraphicManager::Get().SetXScreenOffset( luiXScreenOffset + luiGameWidth - (luiTileWidth*8));
    }
    if (lbMoved)
      miLookingAt += eO_East;
    else
      miLookingAt = eO_East;
  }
 
  if (IsPressed(eIA_Fire))
  {
    cObject *lcBullet = new cBullet(muiX, muiY, miLookingAt, "Bulletblue.png", ePlayer, 2);
    std::stringstream lsNumber;
    lsNumber << miBulletNumber;
    lcBullet->SetName("Bullet"+macName+lsNumber.str());
    miBulletNumber++;
    cLevel::Get().InsertObject(lcBullet);
  }

 if (!lLevel.IsWall( luiX, luiY ))
  {
    muiX = luiX;
    muiY = luiY;
    mfElapsedTime = 0;
    
  }
  
}

//Render player
void cPlayer::Render()
{
  //Get game graphic properties
  int miTileWidth = cGraphicManager::Get().GetTileWidth();
  int miTileHeight = cGraphicManager::Get().GetTileHeight();
  unsigned int luiXScreenOffset = cGraphicManager::Get().GetXScreenOffset();
  unsigned int luiYScreenOffset = cGraphicManager::Get().GetYScreenOffset();
  unsigned int luiGameHeight = cGraphicManager::Get().GetGameHeight();
 
  //Draw the player

  cTexture lTexture = cTextureManager::Get().GetTexture("Data/ship.png");
  int tex1=lTexture.GetID();
  glEnable(GL_TEXTURE_2D);
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  glBindTexture(GL_TEXTURE_2D, tex1);  
  glColor3f(1.0,1.0,1.0);

  float coordx_tile = 0.0f;
  float coordy_tile = 0.0f;

  switch(miLookingAt)
  {
  case eO_South:
    coordx_tile = 0.0f;
    coordy_tile = 0.0f;
    break;
  case eO_North:
    coordx_tile = 0.25f;
    coordy_tile = 0.0f;
    break;
  case eO_West:
    coordx_tile = 0.0f;
    coordy_tile = 0.5f;
    break;
  case eO_East:
    coordx_tile = 0.25f;
    coordy_tile = 0.5f;
    break;
  case eO_NorthWest:
    coordx_tile = 0.50f;
    coordy_tile = 0.5f;
    break;
  case eO_NorthEast:
    coordx_tile = 0.75f;
    coordy_tile = 0.5f;
    break;
  case eO_SouthWest:
    coordx_tile = 0.50f;
    coordy_tile = 0.0f;
    break;
  case eO_SouthEast:
    coordx_tile = 0.75f;
    coordy_tile = 0.0f;
    break;

  }
 
  float ctex = 0.375/2.0;
  float ctey = 0.375;
  glBegin(GL_QUADS);    
    glTexCoord2f(coordx_tile, coordy_tile+ctey);	
    glVertex2i(muiX*miTileWidth, muiY*miTileHeight);
	  glTexCoord2f(coordx_tile+ctex, coordy_tile+ctey);	
    glVertex2i((muiX+1)*miTileWidth , muiY*miTileHeight);
	  glTexCoord2f(coordx_tile+ctex, coordy_tile);	
    glVertex2i((muiX+1)*miTileWidth, (muiY+1)*miTileHeight);
	  glTexCoord2f(coordx_tile, coordy_tile);	
    glVertex2i(muiX*miTileWidth , (muiY+1)*miTileHeight);
  glEnd();  

  DrawHud();
}

void cPlayer::DrawHud()
{
  int miTileWidth = cGraphicManager::Get().GetTileWidth();
  int miTileHeight = cGraphicManager::Get().GetTileHeight();
  unsigned int luiXScreenOffset = cGraphicManager::Get().GetXScreenOffset();
  unsigned int luiYScreenOffset = cGraphicManager::Get().GetYScreenOffset();
  unsigned int luiGameHeight = cGraphicManager::Get().GetGameHeight();
  unsigned int luiGameWidth = cGraphicManager::Get().GetGameWidth(); 

  float coordx_tile = 0.25f;
  float coordy_tile = 0.0f;
  float ctex = 0.375/2.0;
  float ctey = 0.375;
  unsigned int muiX = 0;
  unsigned int muiY = 0;

  //Draw Background
  glDisable(GL_TEXTURE_2D);
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  glColor3f(0.4,0.4,0.4);
  glBegin(GL_QUADS);    
      glVertex2i(luiXScreenOffset, luiYScreenOffset);
      glVertex2i(luiXScreenOffset+miTileWidth*(muiLives)+10 , luiYScreenOffset);
      glVertex2i(luiXScreenOffset+miTileWidth*(muiLives)+10, luiYScreenOffset+miTileHeight+10);
      glVertex2i(luiXScreenOffset , luiYScreenOffset+miTileHeight+10);
    glColor3f(0.0,0.0,0.0);
      glVertex2i(2+luiXScreenOffset, luiYScreenOffset+2);
      glVertex2i(luiXScreenOffset+miTileWidth*(muiLives)+8 , luiYScreenOffset+2);
      glVertex2i(luiXScreenOffset+miTileWidth*(muiLives)+8, luiYScreenOffset+miTileHeight+8);
      glVertex2i(2+luiXScreenOffset , luiYScreenOffset+miTileHeight+8);
  glEnd();  

  //Draw Lives
  cTexture lTexture = cTextureManager::Get().GetTexture("Data/ship.png");
  int tex1=lTexture.GetID();
  glEnable(GL_TEXTURE_2D);
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  glBindTexture(GL_TEXTURE_2D, tex1);  
  glColor3f(1.0,1.0,1.0);

  glBegin(GL_QUADS);    
    for (unsigned int i = 0; i < muiLives ; i++)
    {
      glTexCoord2f(coordx_tile, coordy_tile+ctey);	
      glVertex2i(5+luiXScreenOffset+miTileWidth*i, luiYScreenOffset+5);
	    glTexCoord2f(coordx_tile+ctex, coordy_tile+ctey);	
      glVertex2i(5+luiXScreenOffset+miTileWidth*(i+1) , luiYScreenOffset+5);
	    glTexCoord2f(coordx_tile+ctex, coordy_tile);	
      glVertex2i(5+luiXScreenOffset+miTileWidth*(i+1), luiYScreenOffset+miTileHeight+5);
	    glTexCoord2f(coordx_tile, coordy_tile);	
      glVertex2i(5+luiXScreenOffset+miTileWidth*i , luiYScreenOffset+miTileHeight+5);
    }
  glEnd();  


  if (miPoints <= 0) return;
  
  //Calculate points
  unsigned int luiDiv = miPoints;
  std::list<unsigned int> lvValues;
  unsigned int i = 0;
  while( (luiDiv!= 0))
  {
    lvValues.push_front(luiDiv%10);
    luiDiv = luiDiv /10;
    i++;
  }

  if (lvValues.size()==0) return;

    //Draw Background
    glDisable(GL_TEXTURE_2D);
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glColor3f(0.4,0.4,0.4);
    glBegin(GL_QUADS);    
        glVertex2i(luiXScreenOffset+luiGameWidth-(miTileWidth*lvValues.size())-10, luiYScreenOffset);
        glVertex2i(luiXScreenOffset+luiGameWidth , luiYScreenOffset);
        glVertex2i(luiXScreenOffset+luiGameWidth, luiYScreenOffset+miTileHeight+10);
        glVertex2i(luiXScreenOffset+luiGameWidth-(miTileWidth*lvValues.size())-10, luiYScreenOffset+miTileHeight+10);
        glColor3f(0.0,0.0,0.0);
        glVertex2i(luiXScreenOffset+luiGameWidth-(miTileWidth*lvValues.size())-8, luiYScreenOffset+2);
        glVertex2i(luiXScreenOffset+luiGameWidth - 2 , luiYScreenOffset+2);
        glVertex2i(luiXScreenOffset+luiGameWidth - 2, luiYScreenOffset+miTileHeight+8);
        glVertex2i(luiXScreenOffset+luiGameWidth-(miTileWidth*lvValues.size())-8, luiYScreenOffset+miTileHeight+8);
    glEnd();  


  
    cTexture lTexture2 = cTextureManager::Get().GetTexture("Data/Numbers.png");
    int tex2=lTexture2.GetID();
    glEnable(GL_TEXTURE_2D);
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glBindTexture(GL_TEXTURE_2D, tex2);  
    glColor3f(1.0,1.0,1.0);

    coordx_tile = 0.0f;
    coordy_tile = 0.0f;
    ctex = 24/384.0;
    ctey = 24/32.0;

    glBegin(GL_QUADS);    
    i = lvValues.size();
    for (std::list<unsigned int>::iterator it=lvValues.begin(); it!=lvValues.end(); it++)
      {
        coordx_tile = (*it)*(32/384.0);
      
        glTexCoord2f(coordx_tile, coordy_tile+ctey);	
        glVertex2i(luiXScreenOffset+luiGameWidth-(miTileWidth*i)-5, luiYScreenOffset+5);
	      glTexCoord2f(coordx_tile+ctex, coordy_tile+ctey);	
        glVertex2i(luiXScreenOffset+luiGameWidth-(miTileWidth*(i-1))-5 , luiYScreenOffset+5);
	      glTexCoord2f(coordx_tile+ctex, coordy_tile);	
        glVertex2i(luiXScreenOffset+luiGameWidth-(miTileWidth*(i-1))-5, luiYScreenOffset+miTileHeight+5);
	      glTexCoord2f(coordx_tile, coordy_tile);	
        glVertex2i(luiXScreenOffset+luiGameWidth-(miTileWidth*i)-5 , luiYScreenOffset+miTileHeight+5);
        i--;
      }
    glEnd();  
  

}
//Check if the player has one object
bool cPlayer::HasObject(std::string lsName)
{
  for (std::vector<cObject *>::iterator it = mvObjects.begin(); it != mvObjects.end(); it++)
  {
    if ((*it)->GetName()==lsName) return true;
  }
  return false;
}

//Add an object to player inventary
void cPlayer::GiveObject(cObject *lcObject)
{
  mvObjects.push_back(lcObject);
}

//Remove an object from player inventary
void cPlayer::RemoveObject(std::string lsName)
{
  bool lbRemove = false;
  std::vector<cObject * >::iterator itObj;
  for (std::vector<cObject *>::iterator it = mvObjects.begin(); it != mvObjects.end(); it++)
  {
    if ((*it)->GetName()==lsName) 
    {
      lbRemove = true; 
      itObj = it;
      break;
    }
  }
  if (lbRemove) mvObjects.erase(itObj);
}

//Destructor
cPlayer::~cPlayer()
{
//Remove objects
  for (std::vector<cObject *>::iterator  lcIt = mvObjects.begin(); lcIt != mvObjects.end(); lcIt++)
  {
    delete (*lcIt);
  }
  mvObjects.clear();
}

//The player loose a live
void cPlayer::Kill()
{
  if (muiLives>1)
    cLevel::Get().Restart();
   else
    cGame::Get().Finish();
}